package org.lboot.llog.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Validator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.lboot.core.domain.ResponseDTO;
import org.lboot.jpa.utils.JpaDataUtil;
import org.lboot.llog.anno.ReqFilter;
import org.lboot.llog.module.ApiLogEntity;
import org.lboot.llog.module.ApiLogService;
import org.lboot.llog.module.params.ApiLogQueryParams;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.persistence.criteria.Predicate;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * @author kindear
 * 日志管理监控 CTL
 */
@Slf4j
@RestController
@RequestMapping("monitor")
@AllArgsConstructor
@Api(tags = "日志管理")
public class LLogMonitorController {
    ApiLogService logService;

    @ReqFilter
    @GetMapping("logs")
    @ApiOperation(value = "日志列表")
    public ResponseDTO<Object> logListQuery(ApiLogQueryParams params){

        Pageable pageable = JpaDataUtil.buildPageable(params);
        Specification<ApiLogEntity> spec = (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            if (Validator.isNotEmpty(params.getServices()) && !params.getServices().isEmpty()){
                Predicate p = root.get("serviceName").in(params.getServices());
                list.add(p);
            }
            if (Validator.isNotEmpty(params.getModules()) && !params.getModules().isEmpty()){
                // 条件不为空
                Predicate p1 = root.get("module").in(params.getModules());
                list.add(p1);
            }
            if (Validator.isNotEmpty(params.getActions()) && !params.getActions().isEmpty()){
                Predicate p2 = root.get("action").in(params.getActions());
                list.add(p2);
            }
            // 状态列表
            if (Validator.isNotEmpty(params.getStatuses()) && !params.getStatuses().isEmpty()){
                Predicate p3 = root.get("status").in(params.getStatuses());
                list.add(p3);
            }
            // 操作人
            if (Validator.isNotEmpty(params.getOperatorId())){
                Predicate p4 = cb.equal(root.get("operatorId").as(String.class),params.getOperatorId());
                list.add(p4);
            }
            // 追踪ID
            if (Validator.isNotEmpty(params.getTraceId())){
                Predicate p = cb.equal(root.get("traceId").as(String.class),params.getTraceId());
                list.add(p);
            }
            // 请求关键词检索
            if (Validator.isNotEmpty(params.getReqKey())){
                Predicate p = cb.like(root.get("params"), "%" + params.getReqKey() + "%");
                list.add(p);
            }

            Predicate[] predicates = new Predicate[list.size()];
            return cb.and(list.toArray(predicates));
        };
        return ResponseDTO.succData(
                logService.getAll(pageable,spec)
        );
    }
    @ReqFilter
    @GetMapping("logs/{id}/console")
    @ApiOperation(value = "控制台日志")
    public ResponseDTO<Object> queryLogConsole(@PathVariable("id") Long id){
        ApiLogEntity apiLog = logService.getOneUnwrap(id);
        // 获取追踪ID, 没有追踪ID 或者 成功请求不记录控制台日志
        String traceId = apiLog.getTraceId();
        if (Validator.isEmpty(traceId) || apiLog.getStatus().equals(1)){
            return ResponseDTO.succData(null);
        }
        // 获取文件名
        String currentPath = System.getProperty("user.dir");
        String filePath = currentPath + File.separator + "logs" + File.separator + traceId+".log";
        String content = IoUtil.readUtf8(FileUtil.getInputStream(filePath));
        return ResponseDTO.succData(content);
    }

    @ReqFilter
    @GetMapping("log/modules")
    @ApiOperation(value = "模块列表")
    public ResponseDTO<Object> logModuleList(){
        return ResponseDTO.succData(
                logService.getDistinctModule(false)
        );
    }
}
